package com.zhonglz.controller;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.zhonglz.util.DateUtil;
import com.zhonglz.util.HttpClientUtil;
import com.zhonglz.util.Result;
import com.zhonglz.util.UuidUtils;
import com.zhonglz.util.WeixinPayConfig;
import com.zhonglz.util.WxPayUtil;
import com.zhonglz.util.XmlUtil;

/***
 * 微信jsapi支付接口
 * @author zhonglz
 * 2021年1月6日
 */
@Controller
@RequestMapping("wx/jsApi")
public class WxJsApiPayController {

	private static Logger logger = Logger.getLogger(WxJsApiPayController.class);
	
	
	/***
	 * 微信jsapi公众号支付统一下单请求
	 * @param request
	 * @param response
	 * @return
	 */
	@ResponseBody
	@RequestMapping(value="/payTest")
	public Result payTest(HttpServletRequest request, HttpServletResponse response){
		Result result=new Result();
		String orderNo=DateUtil.getCurrentDateStr(); // 生成订单号
		logger.info("订单号："+orderNo);
		
		Map<String,Object> map=new HashMap<String,Object>();
		map.put("appid", WeixinPayConfig.appid); // 公众账号ID
		logger.info("公众账号ID："+WeixinPayConfig.appid);
		
		map.put("mch_id", WeixinPayConfig.mch_id); // 商户号
		logger.info("商户号："+WeixinPayConfig.mch_id);
		
		map.put("device_info", WeixinPayConfig.device_info); // 设备号
		logger.info("设备号："+WeixinPayConfig.device_info);
		
		String uuid=UuidUtils.uuid();
		map.put("nonce_str", uuid); // 随机字符串
		
		map.put("notify_url", WeixinPayConfig.jsapi_notify_url); // 异步通知地址
		
		map.put("trade_type", "JSAPI"); // 交易类型
		map.put("out_trade_no", orderNo); // 商户订单号
		
		map.put("body", new String("微信jsapi支付测试")); // 商品描述
		
		map.put("total_fee", 1); // 标价金额   微信的金额单位：分
		
		String sjc=String.valueOf(new Date().getTime());
		logger.info("时间戳："+sjc);
		map.put("timeStamp", sjc);
		
		//这里的openid从微信网页授权接口中获取
		map.put("openid", "");//公众号粉丝用户的openid，详细获取方式请参考公众号网页授权获取
		
		map.put("spbill_create_ip", WxPayUtil.getIp(request)); // 终端IP
		map.put("sign", WxPayUtil.getSign(map)); // 签名
		String xml=XmlUtil.genXml(map); 
		logger.info(xml);
		InputStream in = null;
		String prepay_id="";
		try {
			// 发现xml消息
			in = HttpClientUtil.sendXMLDataByPost(WeixinPayConfig.set_order_url, xml).getEntity().getContent();
			prepay_id =WxPayUtil.getElementValue(in,"prepay_id"); // 获取二维码地址
			logger.info("prepay_id:"+prepay_id);
			result.setCode(Result.CODE_SUCCESS);
			result.setMsg("生成prepay_id成功");
			
			Map<String, Object> maps=new HashMap<>();
			maps.put("appId", WeixinPayConfig.appid);
			maps.put("timeStamp", sjc);
			maps.put("nonceStr", uuid);
			maps.put("package", "prepay_id="+prepay_id);
			maps.put("signType", "MD5");
			maps.put("paySign", WxPayUtil.getSign(maps));
			
			result.setObject(maps);
		} catch (Exception e) {
			result.setCode(Result.CODE_EXCEPTION);
			result.setMsg("发送异常");
		}finally{
			// 释放资源
            try {
                if (in != null) in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
		}
		return result;
	 } 
	
	
	/***
	 * 微信jsapi支付回调
	 * @param request
	 * @param response
	 */
	@RequestMapping(value="/wxPayNotify")
	public void wxPayNotify(HttpServletRequest request, HttpServletResponse response){
		logger.info("--------------------微信jsapi支付回调方法执行开始-------------------");
		// 拿到微信回调信息
        try {
        	PrintWriter writer = response.getWriter();
			InputStream in = request.getInputStream();
			SAXReader reader = new SAXReader();
	        Document document=null;
			try {
				document = reader.read(in);
			} catch (DocumentException e) {
				e.printStackTrace();
			}
	        Element root = document.getRootElement();
	        List<Element> childElements = root.elements();
	        logger.info("返回结果如下：");
	        String return_code="";// 返回状态码
	        String result_code="";// 业务结果
	        String mch_id="";// 商户号
	        String nonce_str=""; //随机字符串
	        String transaction_id="";//微信支付订单号
	        String out_trade_no="";//商户订单号
	        int total_fee=0; //订单金额
	        for (Element child : childElements) {
	        	if("return_code".equals(child.getName())){
	        		return_code = child.getStringValue();
	           	}
	        	if("result_code".equals(child.getName())){
	        		result_code = child.getStringValue();
	           	}
	        	if("mch_id".equals(child.getName())){
	        		mch_id = child.getStringValue();
	           	}
	        	if("nonce_str".equals(child.getName())){
	        		nonce_str = child.getStringValue();
	           	}
	        	if("transaction_id".equals(child.getName())){
	        		transaction_id = child.getStringValue();
	           	}
	        	if("out_trade_no".equals(child.getName())){
	        		out_trade_no = child.getStringValue();
	           	}
	        	if("total_fee".equals(child.getName())){
	        		total_fee = Integer.valueOf(child.getStringValue());
	           	}
	        	logger.info(child.getName()+":"+child.getStringValue());
	        }
	        Result result=new Result();
	       
	        logger.info("状态返回码:"+return_code);
			if("SUCCESS".equals(return_code)){
				logger.info("业务结果:"+result_code);
				if("SUCCESS".equals(result_code)){
					logger.info("支付订单号:"+out_trade_no);
					logger.info("这里写业务逻辑");
					/*** 实际验证过程建议商户务必添加以下校验：
				        *  1、需要验证该通知数据中的 out_trade_no 是否为商户系统中创建的订单号
				        *  2、判断 total_fee 是否确实为该订单的实际金额（即商户订单创建时的金额）
						*
						**/
					
					
					// 通知微信订单处理成功
	                String noticeStr = WxPayUtil.setXML("SUCCESS", "");
	                writer.write(noticeStr);
	                writer.flush();
				}
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
		logger.info("--------------------微信jsapi支付回调方法执行结束-------------------");
	}
	

}
